﻿using System;
using System.Collections.Generic;
using System.Text;
using WatiN.Core.Interfaces;
using com.gargoylesoftware.htmlunit.html;

namespace WatiN.Core.HtmlUnit
{
	public class HUElement : INativeElement
	{
		HUBrowser browser;
		HtmlElement element;
		ElementAttributeBag attributeBag;

		public HUElement(HtmlElement element, HUBrowser browser)
		{
			this.element = element;
			this.browser = browser;
		}

		#region INativeElement Members
		public string TextAfter
		{
			get 
			{
				//TODO: Implement
				throw new NotImplementedException();
			}
		}

		public string TextBefore
		{
			get 
			{ 
				//TODO: Implement
				throw new NotImplementedException(); 
			}
		}

		public INativeElement NextSibling
		{
			get { return new HUElement((HtmlElement)element.getNextSibling(), browser); }
		}

		public INativeElement PreviousSibling
		{
			get { return new HUElement((HtmlElement)element.getPreviousSibling(), browser); }
		}

		public INativeElement Parent
		{
			get { return new HUElement((HtmlElement)element.getParentNode(), browser); }
		}

		public string GetAttributeValue(string attributeName)
		{
			string result = null;

			result = element.getAttributeValue(attributeName);

			if (element.getAttribute(attributeName) == null)
				result = "0";

			if (attributeName.ToLowerInvariant().Equals("innertext"))
				result = element.getTextContent();

			return result;
		}

		public void SetAttributeValue(string attributeName, string value)
		{
			value = HandleAttributesWhichHaveNoValuePart(attributeName, value);
			
			element.setAttribute(attributeName, value);
			if (attributeName == "value" && element.getTagName() == "textarea")
				element.setTextContent(value);
		}

		private static string HandleAttributesWhichHaveNoValuePart(string attributeName, string value)
		{
			// selected is attribute of Option
			// checked is attribute of RadioButton and CheckBox
			if (attributeName == "selected" || attributeName == "checked")
			{
				value = bool.Parse(value) ? "true" : "";
			}

			return value;
		}

		public string GetStyleAttributeValue(string attributeName)
		{
			string result = null;

			var styledElem = element as StyledElement;

			if (styledElem != null)
			{
				string css = styledElem.getStyleAttribute();

				System.Collections.Specialized.NameValueCollection styles = new System.Collections.Specialized.NameValueCollection();

				if (!string.IsNullOrEmpty(css))
				{
					string[] cv = css.Split(';');

					foreach (string cvOn in cv)
					{
						if (!string.IsNullOrEmpty(cvOn.Trim()))
						{
							string[] cav = cvOn.Trim().Split(new char[] { ':' }, 2);

							if (cav.Length == 2)
								styles.Add(cav[0].Trim().ToLowerInvariant(), cav[1].Trim().ToLowerInvariant());
						}
					}

					if (styles[attributeName] != null)
						result = styles[attributeName];
				}				
			}

			return result;
		}

		public void SetStyleAttributeValue(string attributeName, string value)
		{
			var styledElem = element as StyledElement;

			if (styledElem != null)
			{
				
			}
		}

		public void ClickOnElement()
		{
			var ce = element as ClickableElement;

			if (ce != null)
			{
				////HtmlPage op =  browser.CurrentPage;
				////HtmlPage np = (HtmlPage)ce.click();
				//string lastUrl = browser.CurrentPage.getWebResponse().getUrl().toURI().toString();
												
				////string html = browser.CurrentPage.asText();

				////browser.CurrentPage = np;

				//HtmlPage np = (HtmlPage)ce.click();

				//string newUrl = np.getPage().getWebResponse().getUrl().toURI().toString();

				//if (!newUrl.Equals(lastUrl))
				//    browser.CurrentPage = np;
				com.gargoylesoftware.htmlunit.Page page = null;
				try
				{
					page = ce.click();
				}
				catch (com.gargoylesoftware.htmlunit.ScriptException)
				{
				}
				finally
				{
					if (page != null && page != browser.CurrentPage)
						browser.CurrentPage = (HtmlPage)page;
				}
			}
		}

		public void SetFocus()
		{
			element.focus();
		}

		public void FireEvent(string eventName, System.Collections.Specialized.NameValueCollection eventProperties)
		{
			//TODO: Not sure if this is right
			element.fireEvent(eventName);
		}

		public string BackgroundColor
		{
			get
			{
				//TODO: Implement
				return string.Empty;
			}
			set
			{
				//TODO: Implement
			}
		}

		public IAttributeBag GetAttributeBag(DomContainer domContainer)
		{
			if (attributeBag == null)
				attributeBag = new ElementAttributeBag(domContainer);
			
			attributeBag.INativeElement = this;

			return attributeBag;
		}

		public bool IsElementReferenceStillValid()
		{
			bool result = false;

			try
			{
				if (element != null)
				{
					if (element.getStartLineNumber() != null && element.getStartLineNumber() > 0)
						result = true;
				}

			}
			catch
			{
				result = false;
			}

			return result;
		}

		public string TagName
		{
			get 
			{
				return element.getTagName();
			}
		}

		public new object Object
		{
			get 
			{
				return element;
			}
		}

		public object Objects
		{
			get 
			{
				List<INativeElement> result = new List<INativeElement>();

				
				org.w3c.dom.NodeList nodes = element.getChildNodes();

				for (int i = 0; i < nodes.getLength(); i++)
					result.Add(new HUElement((HtmlElement)nodes.item(i), browser));

				return result;
			}
		}

		public void FireEventNoWait(string eventName, System.Collections.Specialized.NameValueCollection eventProperties)
		{
			//TODO: Not sure if this is right
			element.fireEvent(eventName);
		}

		public void Select()
		{
			var textinput = element as HtmlTextInput;

			if (textinput != null)
			{
				textinput.select();
			}
			else
			{
				var textarea = element as HtmlTextArea;

				if (textarea != null)
					textarea.select();
			}
		}

		public void SubmitForm()
		{
			HtmlForm form = element.getEnclosingForm();

			if (form != null)
			{
				org.w3c.dom.NodeList nodes = form.getChildNodes();

				for (int i = 0; i < nodes.getLength(); i++)
				{
					var se = nodes.item(i) as SubmittableElement;

					if (se != null)
					{
						form.submit(se);
						break;
					}
				}
	
			}
		}

		#endregion

		
	}
}
